/** 
* @Title: IdcardVerifyUtil.java
* @Package: org.hzzm.cardval.util
* @Description: TODO(身份证验证)
* @author:kevin
* @date:2017年8月8日 下午9:19:12
* @version:V1.0 
*/
package cardval.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class IDcardValUtil {
	 /** 
     * <pre> 
     * 省、直辖市代码表： 
     *     11 : 北京  12 : 天津  13 : 河北       14 : 山西  15 : 内蒙古   
     *     21 : 辽宁  22 : 吉林  23 : 黑龙江  31 : 上海  32 : 江苏   
     *     33 : 浙江  34 : 安徽  35 : 福建       36 : 江西  37 : 山东   
     *     41 : 河南  42 : 湖北  43 : 湖南       44 : 广东  45 : 广西      46 : 海南   
     *     50 : 重庆  51 : 四川  52 : 贵州       53 : 云南  54 : 西藏   
     *     61 : 陕西  62 : 甘肃  63 : 青海       64 : 宁夏  65 : 新疆   
     *     71 : 台湾   
     *     81 : 香港  82 : 澳门   
     *     91 : 国外 
     * </pre> 
     */  
    private static String cityCode[] = { "11", "12", "13", "14", "15", "21",  
            "22", "23", "31", "32", "33", "34", "35", "36", "37", "41", "42",  
            "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62",  
            "63", "64", "65", "71", "81", "82", "91" }; 
    /** 
     * 每位加权因子 
     */  
    private static int power[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5,  
            8, 4, 2 };  
    
    /** 
     * 验证所有的身份证的合法性  18位
     *  
     * @param idcard 
     *            身份证 
     * @return 合法返回true，否则返回false 
     */  
    public static boolean isValidatedAllIdcard(String idcard) {  
        if (idcard == null || "".equals(idcard)) {  
            return false;  
        }   
        return validate18Idcard(idcard);  
    }

	/**
	 * @param idcard
	 * @return
	 */
	public static boolean validate18Idcard(String idcard) {
		// 为空为假
		if (idcard == null) { 
            return false;
		}
		 // 非18位为假  
        if (idcard.length() != 18) {  
            return false;  
        }  
        // 获取前17位  
        String idcard17 = idcard.substring(0, 17);  
  
        // 前17位全部为数字  
        if (!isDigital(idcard17)) {  
            return false;  
        }  
        
        String provinceid = idcard.substring(0, 2);  
        // 校验省份  
        if (!checkProvinceid(provinceid)) {  
            return false;  
        }  
  
        // 校验出生日期   校验年月日这里省掉
        String birthday = idcard.substring(6, 14);  
  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");  
  
        try {  
            Date birthDate = sdf.parse(birthday);  
            String tmpDate = sdf.format(birthDate);  
            if (!tmpDate.equals(birthday)) {// 出生年月日不正确  
                return false;  
            }  
  
        } catch (ParseException e1) {  
  
            return false;  
        }  
     // 获取第18位  
        String idcard18Code = idcard.substring(17, 18);  
  
        char c[] = idcard17.toCharArray();  
  
        int bit[] = converCharToInt(c);  
  
        int sum17 = 0;  
  
        sum17 = getPowerSum(bit);  
  
        // 将和值与11取模得到余数进行校验码判断  
        String checkCode = getCheckCodeBySum(sum17);  
        if (null == checkCode) {  
            return false;  
        }  
        // 将身份证的第18位与算出来的校码进行匹配，不相等就为假  
        if (!idcard18Code.equalsIgnoreCase(checkCode)) {  
            return false;  
        }  
        
		return true; 
	}  
	
	 private static boolean checkProvinceid(String provinceid) {  
	        for (String id : cityCode) {  
	            if (id.equals(provinceid)) {  
	                return true;  
	            }  
	        }  
	        return false;  
	    }  
	  
	    /** 
	     * 数字验证 
	     *  
	     * @param str 
	     * @return 
	     */  
	    private static boolean isDigital(String str) {  
	        return str.matches("^[0-9]*$");  
	    }  
	    
	    /** 
	     * 将身份证的每位和对应位的加权因子相乘之后，再得到和值 
	     *  
	     * @param bit 
	     * @return 
	     */  
	    private static int getPowerSum(int[] bit) {  
	  
	        int sum = 0;  
	  
	        if (power.length != bit.length) {  
	            return sum;  
	        }  
	  
	        for (int i = 0; i < bit.length; i++) {  
	            for (int j = 0; j < power.length; j++) {  
	                if (i == j) {  
	                    sum = sum + bit[i] * power[j];  
	                }  
	            }  
	        }  
	        return sum;  
	    }  
	    
	    /** 
	     * 将和值与11取模得到余数进行校验码判断 
	     *  
	     * @param checkCode 
	     * @param sum17 
	     * @return 校验位 
	     */  
	    private static String getCheckCodeBySum(int sum17) {  
	        String checkCode = null;  
	        switch (sum17 % 11) {  
	        case 10:  
	            checkCode = "2";  
	            break;  
	        case 9:  
	            checkCode = "3";  
	            break;  
	        case 8:  
	            checkCode = "4";  
	            break;  
	        case 7:  
	            checkCode = "5";  
	            break;  
	        case 6:  
	            checkCode = "6";  
	            break;  
	        case 5:  
	            checkCode = "7";  
	            break;  
	        case 4:  
	            checkCode = "8";  
	            break;  
	        case 3:  
	            checkCode = "9";  
	            break;  
	        case 2:  
	            checkCode = "x";  
	            break;  
	        case 1:  
	            checkCode = "0";  
	            break;  
	        case 0:  
	            checkCode = "1";  
	            break;  
	        }  
	        return checkCode;  
	    }  
	    
	    /** 
	     * 将字符数组转为整型数组 
	     *  
	     * @param c 
	     * @return 
	     * @throws NumberFormatException 
	     */  
	    private static int[] converCharToInt(char[] c) throws NumberFormatException {  
	        int[] a = new int[c.length];  
	        int k = 0;  
	        for (char temp : c) {  
	            a[k++] = Integer.parseInt(String.valueOf(temp));  
	        }  
	        return a;  
	    }  
	    
	   /* public static void main(String[] args) {
			String idcard = "362202199801212010";
			System.out.println(isValidatedAllIdcard(idcard));
		}*/
    

}
